package com.gin.kotlin.no_gay_alliance.adapter.reply

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.Typeface
import android.text.Html
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.Switch
import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher
import androidx.core.view.children
import androidx.core.view.contains
import androidx.core.view.isEmpty
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions
import com.gin.kotlin.no_gay_alliance.R
import com.gin.kotlin.no_gay_alliance.activity.PostActivity.Companion.obtainIntent
import com.gin.kotlin.no_gay_alliance.app.App
import com.gin.kotlin.no_gay_alliance.argument.PostPrepareArgument
import com.gin.kotlin.no_gay_alliance.argument.PostPrepareArgument.Action
import com.gin.kotlin.no_gay_alliance.base.AbstractBindingRecyclerViewAdapter
import com.gin.kotlin.no_gay_alliance.base.GlideModule.Companion.CROSS_FADE
import com.gin.kotlin.no_gay_alliance.base.MyHandler
import com.gin.kotlin.no_gay_alliance.base.ViewUtils.Companion.visible
import com.gin.kotlin.no_gay_alliance.databinding.ItemReplyBinding
import com.gin.kotlin.no_gay_alliance.fragment.replylist.ReplyPageFragment
import com.gin.kotlin.no_gay_alliance.model.ReplyStatusModel
import com.gin.kotlin.no_gay_alliance.utils.LogCounter
import com.gin.kotlin.no_gay_alliance.utils.TimeUtils.Companion.DATE_TIME_FORMATTER_MONTH_SECOND
import com.gin.kotlin.no_gay_alliance.utils.TimeUtils.Companion.FULL_DATE_TIME_FORMATTER
import com.gin.kotlin.no_gay_alliance.webview.JsAndroidInterface
import com.gin.nga.enums.FromClient
import com.gin.nga.enums.status.AccountStatus
import com.gin.nga.response.reply.ReplyInfo
import com.gin.nga.response.resource.ui.UiResource
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.time.ZonedDateTime
import java.util.Locale

/**
 * 回复列表适配器
 * @property replyPageFragment ReplyPageFragment
 * @property positionOffset 获取WebView时的偏移量，当评论和热门回复存在时需要提供偏移量
 * @constructor
 */
@Deprecated("暂不考虑使用，仅使用HTML方式渲染")
class ReplyListAdapter(
    context: Context,
    handler: MyHandler,
    private val replyPageFragment: ReplyPageFragment,
    private val launcher: ActivityResultLauncher<Intent>,
    private val positionOffset: Int = 0,
) :
    AbstractBindingRecyclerViewAdapter<ItemReplyBinding, ReplyInfo>(context, handler), View.OnClickListener, JsAndroidInterface {
    override val mLauncher: ActivityResultLauncher<Intent>
        get() = launcher
    override val mActivity: FragmentActivity
        get() = replyPageFragment.requireActivity()

    /**
     * 当显示某一位置的item时的操作
     * @param holder ViewHolder
     * @param position Int
     * @param b ViewBinding
     * @param replyInfo 数据对象
     */
    @SuppressLint("JavascriptInterface")
    override fun onBindViewHolder(holder: ViewHolder<ItemReplyBinding>, position: Int, b: ItemReplyBinding, replyInfo: ReplyInfo) {
        // 点击事件
        listOf(
            b.ivRbbReply,
            b.ivRbbQuote,
        ).forEach { it.setOnClickListener(this); it.tag = replyInfo }

        val logCounter = LogCounter(TAG, replyInfo.floorNumber.toString())
        logCounter.start()
        // 设置显示状态

        // 如果回复ID为空，在用户名处显示警告，隐藏其他窗口
        if (replyInfo.replyId == null) {
            b.root.children.forEach {
                if (it.id == R.id.tv_username) it.visibility = if (it.id == R.id.tv_username) View.VISIBLE else View.GONE
            }
            b.tvUsername.text = SpannableStringBuilder().also { builder ->
                val text = context.getString(R.string.warning_reply_not_found)
                builder.append(text)
                val colorSpan = ForegroundColorSpan(getAttrColor(R.attr.textColorRed))
                builder.setSpan(colorSpan, builder.length - text.length, builder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
                // 加粗
                builder.setSpan(StyleSpan(Typeface.BOLD_ITALIC), builder.length - text.length, builder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
        } else {
            // 检查回复的屏蔽状态
            val blocked = isBlocked(replyInfo)
            // 隐藏除警告信息以外的ui
            b.root.children.forEach {
                if (it.id == R.id.tv_block_warning)
                    it.visibility = if (blocked) View.VISIBLE else View.GONE
                else
                    it.visibility = if (blocked) View.GONE else View.VISIBLE
            }
        }
        logCounter.step("显示状态")

        // 加载头像、小尾巴
        b.ivUserAvatar.also { iv ->
            b.tvTail.text = null
            b.tvTail.visibility = View.GONE
            val avatarBuffId = replyInfo.userInfo?.getAvatarBuffId()
            when {
                //如果是匿名用户，加载匿名头像
                replyInfo.isAnonymous() -> iv.setImageDrawable(getDrawable(R.drawable.ic_person_anonymous_16).also { it?.setTint(getAttrColor(R.attr.textColor)) })
                // 如果有头像id，从列表中加载头像
                avatarBuffId != null -> App.INSTANCE.resourceApi.ui().enqueue(object : Callback<UiResource?> {
                    override fun onResponse(call: Call<UiResource?>, response: Response<UiResource?>) {
                        val buff = response.body()?.avatarBuffs?.firstOrNull { buff -> buff.id == avatarBuffId }
                        if (buff == null) {
                            Log.w(TAG, "buff头像列表为空或ID未匹配：${avatarBuffId}")
                            // 使用默认头像
                            handler.post { iv.setImageDrawable(getDrawable(R.drawable.ic_forum_avatar)) }
                        } else {
                            loadUserAvatar(buff.url, iv)
                            // 设置buff头像和小尾巴
                            handler.post {
                                b.tvTail.visibility = View.VISIBLE
                                b.tvTail.text = buff.suffix
                            }
                        }
                    }

                    override fun onFailure(call: Call<UiResource?>, t: Throwable) {
                        Log.w(TAG, "加载buff头像列表失败")
                        t.printStackTrace()
                    }
                })
                //  加载是一个随机用户头像
                else -> loadUserAvatar(replyInfo.userInfo?.getAvatars()?.random(), iv)
            }
        }

        // 用户名
        b.tvUsername.text = replyInfo.anonymousName ?: replyInfo.userInfo?.username

        logCounter.step("用户名、头像")

        // 账号状态, 正常状态下清空内容，否则按照颜色
        val status = replyInfo.userInfo?.getAccountStatus()
        b.tvAccountStatus.text = Html.fromHtml(
            when (status) {
                AccountStatus.PHONE, AccountStatus.LINK, null -> ""
                else -> "<span style='color:${status.color}'>[${status.cn}]</span>"
            }, Html.FROM_HTML_MODE_COMPACT
        )

        // 楼层号
        b.tvFloorNumber.text = when (replyInfo.floorNumber) {
            null, 0 -> ""
            else -> "${replyInfo.floorNumber}楼"
        }
        // 客户端
        b.tvClient.text = when (replyInfo.client) {
            FromClient.IOS, FromClient.Android, FromClient.PC -> replyInfo.client?.name
            else -> ""
        }
        // 威望
        b.tvPrestige.text = replyInfo.userInfo?.prestige?.div(10.0)?.let { "${replyInfo.userInfo?.groupName}: $it" }

        // 声望
        val level = if (replyInfo.userInfo?.reputationLevel.isNullOrEmpty()) "声望" else replyInfo.userInfo?.reputationLevel
        b.tvReputation.text = replyInfo.userInfo?.reputationValue?.let { "$level (${replyInfo.userInfo?.reputationValue})" }

        // 发帖数
        b.tvPostCount.text = replyInfo.userInfo?.postCount?.let { context.getString(R.string.tv_post_count, replyInfo.userInfo?.postCount.toString()) }

        // 徽章
        val medals = replyInfo.userInfo?.medals
        listOf(b.tvMedal, b.rvMedal).forEach { it.visibility = visible(medals) }
        //todo 填充徽章数据

        // todo 礼物

        logCounter.step("header")
        // 标题
        b.tvTitle.text = replyInfo.title
        b.tvTitle.visibility = visible(replyInfo.title)

        // 被处罚用户修改背景
        b.layoutContent.background = if (!replyInfo.punishedInTopic) null else getDrawable(R.drawable.shape_less_nuke)

        //  回复状态 / 主题状态
        b.tvReplyStatus.text = SpannableStringBuilder().also { builder ->
            ReplyStatusModel.parse(replyInfo).forEach { status ->
                val text = String.format(Locale.CHINESE, "[%s]", status.name)
                builder.append(text)
                val span = ForegroundColorSpan(getAttrColor(status.color))
                builder.setSpan(span, builder.length - text.length, builder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
        }
        b.tvReplyStatus.visibility = visible(b.tvReplyStatus.text)

        // 发帖时间
        b.tvPostTime.text =
            replyInfo.postDatetime?.format(if (ZonedDateTime.now().year == replyInfo.postDatetime?.year) DATE_TIME_FORMATTER_MONTH_SECOND else FULL_DATE_TIME_FORMATTER)

        // 赞数
        b.tvAgreeCount.text = replyInfo.agreeCount?.toString() ?: "0"
        logCounter.step("content")

        // 投票信息
        b.btVoteInfo.visibility = visible(replyInfo.getVoteData())
        if (replyInfo.getVoteData() != null) {
            //todo 投票信息
        }


        // 修改记录
        b.tvLastEdit.text = replyInfo.alterInfo?.lastEdit?.let {
            val user = it.username?.let { i -> "由 $i" } ?: ""
            "修改:${it.timestamp?.format(FULL_DATE_TIME_FORMATTER)} $user"
        }

        // 操作记录
        val logs = replyInfo.alterInfo?.logs
        listOf(b.tvOperationLog, b.rvOperationLog, b.dividerOperationLog).forEach { it.visibility = visible(logs) }
        // 填充数据
        b.rvOperationLog.adapter = (b.rvOperationLog.adapter ?: ReputationLogAdapter(context, handler)).also { (it as ReputationLogAdapter).replaceData(logs) }

        logCounter.step("log")


        // 评论贴条
        b.tvComment.text = context.getString(R.string.tv_comment, replyInfo.comment?.size?.toString() ?: "0")
        configComment(b.tvComment, b.dividerComment, b.rvComment, b.swComment, replyInfo.comment, 100)
        // 热门回复
        b.tvHotReply.text = context.getString(R.string.tv_hot_reply, replyInfo.hotReplies?.size?.toString() ?: "0")
        configComment(b.tvHotReply, b.dividerHotReply, b.rvHotReply, b.swHotReply, replyInfo.hotReplies, 200)

        logCounter.step("评论热门")

        //todo IP属地

        //todo


        /*正文渲染*/
        val t = this

        // 从上级获取一个WebView
        replyPageFragment.obtainWebView(positionOffset + position).also { wv ->
            logCounter.step("开始渲染")
            wv.addJavascriptInterface(this, "android")

            // 如果当前layout并不持有获取到的WebView，则对其内容进行替换
            if (!b.layoutContent.contains(wv)) {
                // 如果当前正文layout非空，清空
                if (!b.layoutContent.isEmpty()) b.layoutContent.removeAllViews()
                // 如果 WebView 有父级，清空父级
                (wv.parent as? ViewGroup)?.removeAllViews()
                // 将WebView 放入正文layout
                b.layoutContent.addView(wv)
            }

            // 加载HTML
            wv.load(replyInfo.getBbsCodeNode(), replyInfo.userInfo?.groupName == "Warden")
            logCounter.step("渲染结束")
        }
        logCounter.stop()
    }

    /**
     * 配置评论贴条和热门回复
     * @param tv TextView
     * @param divider View
     * @param recyclerView RecyclerView
     * @param data List<ReplyInfo>?
     * @param switch 显示开关
     * @param positionOffset 偏移量
     */
    private fun configComment(
        tv: TextView,
        divider: View,
        recyclerView: RecyclerView,
        @SuppressLint("UseSwitchCompatOrMaterialCode") switch: Switch,
        data: List<ReplyInfo>?,
        positionOffset: Int
    ) {
        // 可见性
        listOf(tv, divider, recyclerView, switch).forEach { it.visibility = visible(data) }

        switch.setOnCheckedChangeListener { _, isChecked ->
            recyclerView.visibility = if (isChecked) View.VISIBLE else View.GONE
        }
        // 填充数据
        val adapter = ReplyListAdapter(context, handler, replyPageFragment, launcher, positionOffset)
        adapter.replaceData(data)
        recyclerView.adapter = adapter
    }


    /**
     * 加载用户头像，裁剪为圆形
     * @param url String?
     * @param imageView ImageView
     * @return ViewTarget<(ImageView..ImageView?), (Drawable..Drawable?)>
     */
    private fun loadUserAvatar(url: String?, imageView: ImageView) {
        if (url == null) {
            imageView.setImageDrawable(getDrawable(R.drawable.ic_person_18))
        } else {
            Glide.with(context)
                .load(url)
                .apply(RequestOptions().circleCrop())
                .error(R.drawable.ic_person_18)
                .transition(DrawableTransitionOptions.withCrossFade(CROSS_FADE))
                .placeholder(R.drawable.ic_person_18)
                .into(imageView)
        }
    }

    /**
     * 判断一个回复是否被屏蔽
     * @param dataModel ReplyInfo
     * @return Boolean
     */
    private fun isBlocked(dataModel: ReplyInfo): Boolean {
        //todo

        return false
    }

    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    override fun onClick(v: View?) {
        val data = v?.tag as? ReplyInfo ?: return
        when (v.id) {
            R.id.iv_rbb_reply -> launcher.launch(obtainIntent(context, PostPrepareArgument(Action.REPLY, topicId = data.topicId, replyId = data.replyId)))
            R.id.iv_rbb_quote -> launcher.launch(obtainIntent(context, PostPrepareArgument(Action.QUOTE, topicId = data.topicId, replyId = data.replyId)))
        }
    }
}